package com.hcj.springcloud.map;

import org.junit.Test;

import java.util.*;

/**
 * 重新hashCode和equals, 对hashSet和Set的影响
 */
public class MapDemo {
    private Person person1 = new Person(1, "a" + "b");
    private Person person2 = new Person(1, "ba");
    private Person person3 = new Person(1, "ab");
    private Person person4 = new Person(2, "b");
    private Person person5 = new Person(2, "c");



    {
        System.out.println("父类非静态代码块执行");
        List list = new ArrayList(2);
        list.add(0);
        list.add(1);
        Object x = list.set(1, "x");
        Object y = list.set(1, "y");
        List arrayList = Arrays.asList("1,2,3");
        Set set = new HashSet(list);
    }




    @Test
    public void test_hashMap() {
        Map map = new HashMap();
        map.put("1", person1);
        map.put("2", person2);
        map.put("3", person3);
        map.put("4", person4);
        map.put("5", person5);

        map.forEach((k, v) -> {
            System.out.println(k + " \t " + v);
        });
    }

    @Test
    public void test_hashSet() {
        HashSet<Person> hashSet = new HashSet<>();
        hashSet.add(person1);
        hashSet.add(person2);
        hashSet.add(person3);
        hashSet.add(person4);
        hashSet.add(person5);

        hashSet.forEach((v) -> {
            System.out.println(v);
        });

        System.out.println("person1 == person3 " + (person1 == person3));
        System.out.println("person1.equals(person3) " + (person1.equals(person3)));


        System.out.println("person1 内存地址等于 person3 " + (person1.equals(person3)));

        Object a = new String("a");
        Object b = new String("b");
        Object c = new String("b");
        String d = "a";
        String e = "b";
        String f = "a" + "b";
        String g = new String("ab");
        String h = "a";
        String i = "a" + e;
        String j = "a" + "b";

        System.out.println(" b == c " + (b == c)); // false
        System.out.println(" b == e " + (b == e)); // false
        System.out.println(" b equals c " + (b.equals(c))); // true
        System.out.println(" a equals d " + (a.equals(d))); // true
        System.out.println(" f equals g " + (f.equals(g))); // true
        System.out.println(" f == g " + (f == g)); // false
        System.out.println(" f ==  (d + e) " + (f == (d + e))); //false
        System.out.println(" h ==  d " + (h == d)); // true
        System.out.println(" f ==  i " + (f == i)); // false
        System.out.println(" f ==  j " + (f == j)); // true

    }


    @Test
    public void tableSizeFor() {
        int x = Integer.MAX_VALUE;
        // 这里为什么不用 整数的最大值，是因为cap 要能被2整除
        int cap = 1 << 30;
        int n = cap - 1;
        System.out.println(n + "第一次 n>>>1: \t" + (n >>> 1));
        n = n >>> 1 | n;
        System.out.println(n + "第一次 n>>>2: \t" + (n >>> 2));
        n = n >>> 2 | n;
        System.out.println(n + "第一次 n>>>4: \t" + (n >>> 4));
        n = n >>> 4 | n;
        System.out.println(n + "第一次 n>>>8: \t" + (n >>> 8));
        n = n >>> 8 | n;
        System.out.println(n + "第一次 n>>>16: \t" + (n >>> 16));
        n = n >>> 16 | n;
        int size = (n < 0) ? 1 : (n >= 1 << 30) ? 1 << 30 : n + 1;
        System.out.println(size);
    }


    @Test
    public void tableSizeForSrc() {
        int cap = 13;
        int n = cap - 1;
        n |= n >>> 1;
        System.out.println("第一次 n>>>1: \t" + n);
        n |= n >>> 2;
        System.out.println("第一次 n>>>2: \t" + n);
        n |= n >>> 4;
        System.out.println("第一次 n>>>4: \t" + n);
        n |= n >>> 8;
        System.out.println("第一次 n>>>8: \t" + n);
        n |= n >>> 16;
        System.out.println("第一次 n>>>16: \t" + n);
        int size = (n < 0) ? 1 : (n >= 1 << 30) ? 1 << 30 : n + 1;
        System.out.println(size);
    }

    /**
     * 快速幂算法求n的m次方
     * 实现原理：
     * 在数学中，存在等式n^m = n^(m1+m2+m3+.....+mk) = n^m1 * n^m2 * n^m3 * ...* n^mk， 且m1 + m2 + m3 +....+mk = m
     * 我们计算m的二进制，如上示例幂数7的二进制=0000 0111，他的十进制计算为： 1+2+4，所以5^7 = 5^(1+2+4) = 5^1 * 5^2 * 5^4，可以看出时间复杂度为f（n）=lgn
     * @param n
     * @param m
     * @return
     */
    public static int power(int n, int m) {
        int temp = 1, base = n;
        while (m != 0)  {
            if ((m & 1) == 1) {  // 判断奇偶,
                temp = temp * base;
            }
            base = base * base;
            m >>= 1;   // 舍弃尾部位
        }
        return temp;
    }

    @Test
    public void nDeMCiMi() {
        System.out.println("3的3次方 = " + power(3,3));
        System.out.println("5的8次方 = " + power(5,8));
    }
}
